package simple.form.core;

import org.apache.log4j.Logger;
import simple.form.cache.CacheManager;
import simple.form.core.annotation.ParameterBeanField;
import simple.form.core.annotation.ParameterBean;
import simple.form.utils.ClassUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 请求参数bean管理类
 * Created by Administrator on 2017/2/15.
 */
public class ParameterBeanManager {

    public static Logger log4j = Logger.getLogger(ParameterBeanManager.class);

    public static final int BYTE =0;
    public static final int SHORT =1;
    public static final int INT =2;
    public static final int  LONG=3;
    public static final int FLOAT =4;
    public static final int DOUBLE =5;
//    public static final int CHART =6;
    public static final int BOOLEAN =7;

    public static final int BYTE_CLASS =8;
    public static final int SHORT_CLASS =9;
    public static final int INT_CLASS =10;
    public static final int LONG_CLASS=11;
    public static final int FLOAT_CLASS =12;
    public static final int DOUBLE_CLASS =13;
//    public static final int CHART_CLASS =14;
    public static final int BOOLEAN_CLASS =15;

    public static final int STRING =16;

    public static final int DATE = 17;
    /**
     * 请求参数的数据类型
     */
    public static final Map<String,Integer> type = new HashMap<String,Integer>(){{
        put("byte",BYTE);
        put("short",SHORT);
        put("int",INT);
        put("long",LONG);
        put("float",FLOAT);
        put("double",DOUBLE);
//        put("char",CHART);
        put("boolean",BOOLEAN);

        put("class java.lang.Byte",BYTE_CLASS);
        put("class java.lang.Short",SHORT_CLASS);
        put("class java.lang.Integer",INT_CLASS);
        put("class java.lang.Long",LONG_CLASS);
        put("class java.lang.Float",FLOAT_CLASS);
        put("class java.lang.Double",DOUBLE_CLASS);
//        put("class java.lang.Character",CHART_CLASS);
        put("class java.lang.Boolean",BOOLEAN_CLASS);

        put("class java.lang.String",STRING);

        put("class java.util.Date",DATE);
    }};
    /***
     * 参数bean的字段类型映射
     * Map<"bean",Map<"fieldName","fieldType">>  其中bean为扫描出的bean的名称(类的全名)，fieldName为该bean的字段，fieldType位该bean的字段类型
     */
    public static final Map<Class,Map<String,String>> beanFieldType = new HashMap<>();


    /***
     * 参数bean的字段注解的映射
     * Map<"bean的类名",Map<"字段名称",Map<"注解名称","注解值">>
     */
    public static final Map<Class,Map<String,Map<String,Object>>> beanFieldAnnotation = new HashMap<>();


    private static  volatile  ParameterBeanManager parameterBeanManager;
    private ParameterBeanManager(){

    }
    public  static ParameterBeanManager getInstance(){
        if (parameterBeanManager == null) {
            synchronized (ParameterBeanManager.class) {
                if (parameterBeanManager == null) {
                    parameterBeanManager = new ParameterBeanManager();
                }
            }
        }
        return parameterBeanManager;
    }

    /**
     * 初始化,扫描bean
     * @param packageName
     */
    public  ParameterBeanManager init(String packageName){
        log4j.info(String.format("ParameterBeanManager init,packageName{%s}", packageName));
        List<Class<?>> classes = ClassUtil.getClasses(packageName);
        //是否有注解
        boolean hasAnnotation;
        String fieldType = null;
        String fieldName = null;
        Class currentclas;
        for (Class clas :classes) {
            hasAnnotation =  clas.isAnnotationPresent(ParameterBean.class);
            if(hasAnnotation){
                currentclas = clas;
                beanFieldType.put(clas,new HashMap<>());
                beanFieldAnnotation.put(clas,new HashMap<>());

                Field[] fields = clas.getDeclaredFields();
                for(Field field : fields){
                    fieldName = field.getName();
                    fieldType = field.getType().toString();
                    if((fieldName!=null&&fieldName.length()>0)&&(fieldType!=null&&fieldType.length()>0)){
                        if(currentclas!=null){
                            beanFieldType.get(currentclas).put(fieldName,fieldType);
                            if(field.isAnnotationPresent(ParameterBeanField.class)){
                                beanFieldAnnotation.get(currentclas).put(fieldName,new HashMap<>());
                            }
                        }
                    }


                    //字段的注解
                    Annotation[] annotations = field.getAnnotations();
                    for(Annotation annotation:annotations) {
                        Method[] methods = annotation.annotationType().getDeclaredMethods();
                        for (Method method : methods) {
                            //获取method为value的method
                            try {
                                if (ParameterBeanField.IS_REGEX.equals(method.getName())) {
                                    Object invoke = null;
                                    invoke = method.invoke(annotation);
                                    beanFieldAnnotation.get(currentclas).get(fieldName).put(ParameterBeanField.IS_REGEX,invoke);
                                }
                                if (ParameterBeanField.TIP.equals(method.getName())) {
                                    Object invoke = null;
                                    invoke = method.invoke(annotation);
                                    beanFieldAnnotation.get(currentclas).get(fieldName).put(ParameterBeanField.TIP,invoke);

                                }
                                if (ParameterBeanField.IS_NULL.equals(method.getName())) {
                                    Object invoke = null;
                                    invoke = method.invoke(annotation);
                                    beanFieldAnnotation.get(currentclas).get(fieldName).put(ParameterBeanField.IS_NULL,invoke);
                                }
                                if (ParameterBeanField.REGEX.equals(method.getName())) {
                                    Object invoke = null;
                                    invoke = method.invoke(annotation);
                                    beanFieldAnnotation.get(currentclas).get(fieldName).put(ParameterBeanField.REGEX,invoke);
                                }
                            } catch (IllegalAccessException e) {
                                log4j.error(e.getMessage(),e);

                            } catch (InvocationTargetException e) {
                                log4j.error(e.getMessage(),e);
                            }
                        }
                    }
                }
            }

        }
        return this;
    }
}
